/* main.c for !ResCreate */


#include "main.h"
#include "dbox.h"



/* the toolbox id block */

static IdBlock idblk;
static WimpPollBlock pblock;


/* events */

#define  Event_Quit             1
#define  Event_SaveRes_Object   2
#define  Event_SaveText_Object  3
#define  Event_SaveRes_Gadget   4
#define  Event_SaveText_Gadget  5


/* static data */

static int messages [] = {0};    /* all messages */
static int tbcodes  [] = {0};    /* all Toolbox events */

static Bool quit = FALSE;        /* set TRUE to terminate poll loop */


/* objects */

static ObjectId iconbaricon;    /* IconBar object */

static ObjectId objdbox;        /* object definition dbox */
static ObjectId gadgdbox;       /* gadget definition dbox */

static ObjectId saveresobj;     /* SaveAs for object as resource */
static ObjectId savetextobj;    /* SaveAs for object as text */
static ObjectId saveresgadg;    /* SaveAs for gadget as resource */
static ObjectId savetextgadg;   /* SaveAs for gadget as text */


/* reference for scrap data transfer protocol */

static int scrap_ref = -1;



/*
 * Another application is trying to transfer data to us. We accept only if
 *  the drop is onto our icon on the icon bar, and the file is of type text;
 *  then we will support a scrap transfer.
 */

static Bool datasave_handler (WimpMessage *message, void *handle)
{
    
    IGNORE (handle);

    /* only accept text files dropped on the icon bar icon */
    if (message->data.data_save.destination_window == WimpWindow_Iconbar &&
        message->data.data_save.file_type == 0xfff)
    {
        /* reply with DataSaveAck for scrap transfer */
        message->hdr.your_ref = message->hdr.my_ref;
        message->hdr.action_code = Wimp_MDataSaveAck;
        message->data.data_save_ack.estimated_size = -1;
        strcpy (message->data.data_save_ack.leaf_name, "<Wimp$Scrap>");
        message->hdr.size = offsetof (WimpMessage, data) +
                            offsetof (WimpDataSaveAckMessage, leaf_name) +
           (((strlen (message->data.data_save_ack.leaf_name) + 1) + 3) & ~3);
        EDG (ret, wimp_send_message (Wimp_EUserMessage, (void *) message,
                                                 message->hdr.sender, 0, 0));
        scrap_ref = message->hdr.my_ref;
    }

  ret:
    return TRUE;
}


/*
 * The user has dragged an icon from a filer window - or this is part of a
 *  DataSave scrap transfer (see datasave_handler(..) above).
 *
 * We load the file (ignoring it silently if the format is not right), and
 *  delete the file if it is <Wimp$Scrap>.
 */

static Bool dataload_handler (WimpMessage *message, void *handle)
{
    IGNORE (handle);

    /* check file type and drop position */
    if (message->data.data_load.destination_window == WimpWindow_Iconbar &&
        message->data.data_load.file_type == 0xfff)
    {
        ObjectId dbox;

        /* try to load the file */
        dbox = dbox_load_from_file (message->data.data_load.leaf_name,
                                                          objdbox, gadgdbox);

        /* show the dbox if it has been loaded */
        if (dbox != 0)
            EDG (ret, toolbox_show_object (0, dbox, 0, 0, 0, 0));

        /* delete scrap file if this was a scrap transfer */
        if (message->hdr.your_ref == scrap_ref)
        {
            scrap_ref = -1;

            /* delete Wimp$Scrap */
            EDG (ret, _swix (OS_File, I0|I1, 6, "<Wimp$Scrap>"));
        }

        /* respond DataLoadAck */
        message->hdr.your_ref = message->hdr.my_ref;
        message->hdr.action_code = Wimp_MDataLoadAck;
        EDG (ret, wimp_send_message (Wimp_EUserMessage, (void *) message,
                                                 message->hdr.sender, 0, 0));
    }

  ret:
    return TRUE;
}


static Bool save_handler
(
    int code,
    ToolboxEvent *event,
    IdBlock *idblock,
    void  *handle
)
{
    char * (*dbox_save_func) (ObjectId, Bool, int*);
    Bool isobject;
    ObjectId saveas;
    char *buff;
    int size;
    WimpGetPointerInfoBlock pointerinfo;

    IGNORE(event);
    IGNORE(handle);
    IGNORE(idblock);

    switch (code)
    {
    case Event_SaveRes_Object:
        dbox_save_func = dbox_save;
        isobject = TRUE;
        saveas = saveresobj;
        break;

    case Event_SaveText_Object:
        dbox_save_func = dbox_save_as_text;
        isobject = TRUE;
        saveas = savetextobj;
        break;

    case Event_SaveRes_Gadget:
        dbox_save_func = dbox_save;
        isobject = FALSE;
        saveas = saveresgadg;
        break;

    case Event_SaveText_Gadget:
        dbox_save_func = dbox_save_as_text;
        isobject = FALSE;
        saveas = savetextgadg;
        break;
    }

    /* construct block of data to be saved */
    buff = dbox_save_func (isobject ? objdbox : gadgdbox, isobject, &size);
    if (!buff)
        return TRUE;

    /* tell SaveAs object to save this data */
    EDG (ret, saveas_set_data_address (0, saveas, buff, size, 0, 0) );

    /* find the mouse position */
    EDG (ret, wimp_get_pointer_info (&pointerinfo) );

    /* and display the SaveAs object close to it */
    pointerinfo.x -= 40;
    pointerinfo.y += 40;
    EDG (ret, toolbox_show_object (1, saveas, 2, &pointerinfo, 0, 0) );

  ret: 
    return TRUE;
}


static Bool toolbox_error
(
    int code,
    ToolboxEvent *event,
    IdBlock *idblock,
    void  *handle
)
{
    ToolboxErrorEvent *t = (ToolboxErrorEvent *) event;
    error e;

    IGNORE(code);
    IGNORE(handle);
    IGNORE(idblock);

    e.errnum = t->errnum;
    strcpy (e.errmess, t->errmess);

    error_box (&e);

    return TRUE;
}


static Bool proginfo_show
(
    int code,                 /* event code [ProgInfo_AboutToBeShown] */
    ToolboxEvent *event,      /* Toolbox event block */
    IdBlock *idblock,         /* Toolbox Id block */
    void  *handle             /* user handle [0] */
)
{
    IGNORE(handle);
    IGNORE(event);
    IGNORE(code);
                          
    proginfo_set_version
    (
        0,                          /* flags */
        idblock->self_id,           /* object ID */
        message_lookup("Version")     /* version string */
    );

    return TRUE;
}


static Bool tbquit_handler
(
    int code,
    ToolboxEvent *event,
    IdBlock *idblock,
    void  *handle
)
{
    IGNORE(event);
    IGNORE(code);
    IGNORE(handle);
    IGNORE(idblock);

    quit = TRUE;
    return TRUE;
}


static Bool quit_handler (WimpMessage *message, void *handle)
{
    IGNORE (message);
    IGNORE (handle);

    quit = TRUE;
    return TRUE;
}


/*
 * Initialise the task (we use toolbox_initialise instead of wimp_initialise)
 * and register any events handlers.
 */

static error * app_init (void)
{
    /* initialise as a toolbox task */
    ER ( toolbox_initialise
         (
          /* IN */
             0,              /* flags */
             310,            /* earliest permissible WIMP version */
             messages,       /* list of interesting messages */
             tbcodes,        /* list of interesting Toolbox event codes */
             APPDIR,         /* name of directory containing resources */
             &mbl,           /* for the Messages file descriptor */
             &idblk,         /* address of toolbox id block */
          /* OUT */
             NULL,           /* current Wimp version */
             NULL,           /* task handle */
             NULL            /* sprite area */
         ) );
                          
    /* initialise event lib */
    ER ( event_initialise (&idblk) );
    
    /* Register handler for toolbox error events */
    ER ( event_register_toolbox_handler
         (
             -1,
             Toolbox_Error,
             toolbox_error,
             NULL
         ) );

    /* "Quit" message from Wimp */
    ER ( event_register_message_handler
         (
             Wimp_MQuit,     /* the Wimp Message */
             quit_handler,   /* the handler function for it */
             NULL            /* and a handle */
         ) );

    /* User chooses "Quit" entry from iconbar menu */
    ER ( event_register_toolbox_handler
         (
             -1,             /* for all objects */
             Event_Quit,     /* toolbox event code */
             tbquit_handler, /* the handler function for it */
             NULL            /* and a handle */
         ) );

    /* "ProgInfo" object is about to be shown */
    ER ( event_register_toolbox_handler
         (
             -1,
             ProgInfo_AboutToBeShown,
             proginfo_show,
             NULL
         ) );

    /* User clicks "Save" in object definition dbox */
    ER ( event_register_toolbox_handler
         (
             -1,
             Event_SaveRes_Object,
             save_handler,
             NULL
         ) );

    /* User clicks "Save as text" in object definition dbox */
    ER ( event_register_toolbox_handler
         (
             -1,
             Event_SaveText_Object,
             save_handler,
             NULL
         ) );

    /* User clicks "Save" in gadget definition dbox */
    ER ( event_register_toolbox_handler
         (
             -1,
             Event_SaveRes_Gadget,
             save_handler,
             NULL
         ) );

    /* User clicks "Save as text" in gadget definition dbox */
    ER ( event_register_toolbox_handler
         (
             -1,
             Event_SaveText_Gadget,
             save_handler,
             NULL
         ) );

    /* DataSave message (attempted transfer from another application) */
    ER ( event_register_message_handler
         (
             Wimp_MDataSave,
             datasave_handler,
             NULL
         ) );

    /* DataLoad message (from the Filer, or as part of a scrap transfer) */
    ER ( event_register_message_handler
         (
             Wimp_MDataLoad,
             dataload_handler,
             NULL
         ) );


    /* create iconbar icon and show it */
    ER ( toolbox_create_object (0, "AppIcon", &iconbaricon) );

    /* note ids of the two definition dialogue boxes */
    ER ( iconbar_get_show (3, iconbaricon, &objdbox, &gadgdbox) );

    /* create the four SaveAs objects for future reference */
    ER ( toolbox_create_object (0, "SaveRes", &saveresobj) );
    ER ( toolbox_create_object (0, "SaveRes", &saveresgadg) );
    ER ( toolbox_create_object (0, "SaveText", &savetextobj) );
    ER ( toolbox_create_object (0, "SaveText", &savetextgadg) );


    return NULL;
}                                                              


int main (int argc, char *argv[])
{
    int code;

    /* set up debug output if DEBUG is set */
    debug_file(APPDIR".logfile");
                     
    EE ( app_init() );

    /* disable NULL events and KeyPress events */
    event_set_mask (0x101);

    while (!quit)
       ED ( event_poll
            (
                &code,      /* event code */
                &pblock,    /* Wimp poll block */
                NULL        /* address of poll word (if necessary) */
            ) );

    exit (0);
}
